/*
 * Calendario
 * v1.0
 * Arcadio Carballares Martin, 2009
 * http://www.carballares.es/arcadio
 */
package tham.com.arcadiocarballares {
	import flash.events.MouseEvent;
	
	import mx.collections.ArrayCollection;
	import mx.containers.Box;
	import mx.containers.Canvas;
	import mx.containers.HBox;
	import mx.containers.Tile;
	import mx.controls.ComboBox;
	import mx.controls.Label;
	import mx.controls.NumericStepper;
	import mx.events.ListEvent;
	import mx.events.NumericStepperEvent;
	
	[Event(name="selectDay", type="tham.com.arcadiocarballares.SelectDayEvent")]
	[Event(name="deselectDay", type="tham.com.arcadiocarballares.SelectDayEvent")]
	
	[Bindable]
	public class Calendario extends Canvas {
		public var dayNames:Array=new Array('Su', 'Mo','Tu','We','Th','Fr','Sa');
		public var monthNames:Array=new Array('January', 'February', 'March', 'April', 'May',
      		'June', 'July', 'August', 'September', 'October', 'November',
      		'December');
      	public var selectedDate:DayData;
      	public var selectedDates:ArrayCollection;
      	public var rowCount:int=9;
      	public var firstWeekDay:int=1;
      	
		private var _events:ArrayCollection;
		public function set events(value:ArrayCollection):void {
			_events=value;
			invalidateProperties();
		}
		public function get events():ArrayCollection {
			return _events;
		}
		
		private var _tileWidth:int=24;		
		public function set tileWidth(value:int):void {
			_tileWidth=value;
			setDateChooserWidth();
		}
		public function get tileWidth():int {
			return _tileWidth;
		}
		
		private var _tileHeight:int=20;		
		public function set tileHeight(value:int):void {
			_tileHeight=value;
			setDateChooserHeight();
		}
		public function get tileHeight():int {
			return _tileHeight;
		}
		
		private var bg:Box;
		private var headerContent:HBox;
		private var weekContent:HBox;
		private var centralContent:Tile;
		private var titleYear:NumericStepper;
		private var titleMonth:ComboBox;
		
		private var today:Date;
		private var year:int;
		private var month:int;
		private var dateChooserWidth:int;
		private var dateChooserHeight:int;
		
		private const HEADER_HEIGHT:int=30;
		private const WEEK_HEIGHT:int=20;
		private const BG_PADDING:int=5;
		private const CENTRAL_PADDING:int=5;
		private const HEADER_PADDING:int=2;
		private const HORIZONTAL_GAP:int=2;
		private const VERTICAL_GAP:int=2;
		private const TOTAL_DAYS:int=42;
		
		public function Calendario() {
			today = new Date();
			year = today.getFullYear();
			month = today.getMonth();
			setDateChooserWidth();
			setDateChooserHeight();
			selectedDates=new ArrayCollection();
			
			horizontalScrollPolicy='off';
			verticalScrollPolicy='off';
			setStyle('backgroundColor','white');
		}
		
		private function setDateChooserWidth():void {
			dateChooserWidth=(tileWidth*7)+(HORIZONTAL_GAP*6)+(BG_PADDING*2)+(CENTRAL_PADDING*2);
		}
		
		private function setDateChooserHeight():void {
			dateChooserHeight=(tileHeight*6)+(VERTICAL_GAP*5)+HEADER_HEIGHT+WEEK_HEIGHT+
				(BG_PADDING*2)+(CENTRAL_PADDING*2);
		}
		
		override protected function commitProperties():void {
			titleYear.value=year;
			titleMonth.selectedIndex=month;
			buildDays();
			// Check today y lo pinta
			//if (year == today.getFullYear() && month == today.getMonth()) {
				//Day(centralContent.getChildByName('day'+today.getDate())).setToday();
			//}
			// Check events and disabled
			checkEvents();
		}
		
		override protected function createChildren():void {
			super.createChildren();
			
			var innerWidth:int=(tileWidth*7)+(HORIZONTAL_GAP*6)+(CENTRAL_PADDING*2);
			
			// General
			bg = new Box();
			bg.percentWidth=100;
			bg.setStyle('verticalGap',0);
			bg.setStyle('paddingTop',BG_PADDING);
			bg.setStyle('paddingBottom',BG_PADDING);
			bg.setStyle('paddingLeft',BG_PADDING);
			bg.setStyle('paddingRight',BG_PADDING);
			
			// Header
			headerContent = new HBox();
			headerContent.width=innerWidth;
			headerContent.height=HEADER_HEIGHT;
			headerContent.setStyle('paddingTop',HEADER_PADDING);
			headerContent.setStyle('paddingBottom',HEADER_PADDING);
			headerContent.setStyle('paddingLeft',HEADER_PADDING);
			headerContent.setStyle('paddingRight',HEADER_PADDING);
			headerContent.setStyle('verticalAlign','middle');
			headerContent.setStyle('backgroundAlpha',0.8);
	     	headerContent.setStyle('backgroundColor','#F0B081');
			headerContent.setStyle('cornerRadius',5);
			headerContent.setStyle('borderStyle','solid');
			headerContent.setStyle('borderThickness',0);
			
			// Year and Month
			titleYear=new NumericStepper();
			titleYear.addEventListener(NumericStepperEvent.CHANGE, onChangeYear);
			titleYear.maximum=9999;
			titleYear.value=year;
			titleYear.percentWidth=100;
			titleYear.maxWidth=60;
			titleYear.setStyle('textAlign','center');
			
			titleMonth=new ComboBox();
			titleMonth.addEventListener(ListEvent.CHANGE, onChangeMonth);
			titleMonth.rowCount=rowCount;
			titleMonth.dataProvider=monthNames;
			titleMonth.selectedIndex=month;
			titleMonth.percentWidth=100;
			headerContent.addChild(titleMonth);
			headerContent.addChild(titleYear);

			// Week
			weekContent=new HBox();
			weekContent.width=innerWidth;
			weekContent.height=WEEK_HEIGHT;
			weekContent.setStyle('horizontalGap',0);
			weekContent.setStyle('verticalAlign','middle');
			//weekContent.setStyle('backgroundColor','green');
			for each(var item:String in dayNames) {
    			var it:Label=new Label();
    			it.text=item;
    			it.setStyle('textAlign','center');
    			it.percentWidth=100;
    			weekContent.addChild(it);
  			}

			// Central
			centralContent = new Tile();
			centralContent.width=innerWidth;
			centralContent.height=(tileHeight*6)+(VERTICAL_GAP*5)+(CENTRAL_PADDING*2);
			centralContent.tileWidth=tileWidth;
			centralContent.tileHeight=tileHeight;
			centralContent.setStyle('cornerRadius',10);
			centralContent.direction='horizontal';
			centralContent.setStyle('horizontalAlign', 'center');
			centralContent.setStyle('horizontalGap', HORIZONTAL_GAP);
			centralContent.setStyle('verticalGap', VERTICAL_GAP);
			centralContent.setStyle('paddingTop',CENTRAL_PADDING);
			centralContent.setStyle('paddingBottom',CENTRAL_PADDING);
			centralContent.setStyle('paddingLeft',CENTRAL_PADDING);
			centralContent.setStyle('paddingRight',CENTRAL_PADDING);
			centralContent.setStyle('textAlign','center');
	     	centralContent.setStyle('font-weight','bold');
	     	centralContent.setStyle('backgroundAlpha',0.4);
	     	centralContent.setStyle('backgroundColor','#F0B081');
	     	centralContent.setStyle('cornerRadius',5);
			centralContent.setStyle('borderStyle','solid');
			centralContent.setStyle('borderThickness',0);
			
			// Add components
			bg.addChild(headerContent);
			bg.addChild(weekContent);
			bg.addChild(centralContent);
			addChild(bg);
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			// Dimensions are relative 'tileWidth' and 'tileHight'
			titleMonth.dataProvider=monthNames;
			width=dateChooserWidth;
			height=dateChooserHeight;
		}
		
		private function buildDays():void {
			// clear previous
			centralContent.removeAllChildren();
			selectedDate=null;
			selectedDates=new ArrayCollection();
			// --
			var daysMonth:int=calculateDaysMonth();
			var initialDay:int=calculateInitialDay();
			var day:Day;
			// Previous month days
			for (var i:int=initialDay+firstWeekDay;i>0;i--) {
				day=new Day();
				day.alpha=0.5;
				day.enabled=false;
				centralContent.addChild(day);
			}
			// Actual month	days
			for (var j:int=1;j<=daysMonth;j++) {
				day=new Day();
				day.dayData=new DayData();
				day.dayData.eventDate=new Date(year+'/'+(month+1)+'/'+j);
				day.name='day'+j;
				day.label=''+j;
				day.addEventListener(MouseEvent.CLICK, onDayClick);
				centralContent.addChild(day);
			}
			// Next month days
			for (var k:int=TOTAL_DAYS-initialDay-firstWeekDay;k>daysMonth;k--) {
				day=new Day();
				day.alpha=0.5;
				day.enabled=false;
				centralContent.addChild(day);
			}
		}
		
		private function onChangeYear(event:NumericStepperEvent):void {
			year=event.value;
			invalidateProperties();
		}
		
		private function onChangeMonth(event:ListEvent):void {
			month=event.target.selectedIndex;
			invalidateProperties();
		}
		
		private function calculateInitialDay():int {
			var myDate:Date=new Date(year,month,0);
			return myDate.getDay();
		}
		
		private function calculateDaysMonth():int {
			var days:int;
			switch (month) {
				case 0:
					days=31; // January
					break;
				case 1:
					days=isLeap(); // February
					break;
				case 2:
					days=31; // March
					break;
				case 4:
					days=31; // May
					break;
				case 6:
					days=31; // July
					break;
				case 7:
					days=31; // August
					break;
				case 9:
					days=31; // October
					break;
				case 11:
					days=31; // December
					break;
				default:
					days=30; // 30 days months
					break;
			}
			return days;
		}
		
		private function isLeap():int {
			if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
	            return 29;
	        } else {
	            return 28;
	        }
		}
		
		private function checkEvents():void {
			for each (var item:DayData in events) { 
			    if (item.eventDate.getMonth()==month && 
			    	item.eventDate.getFullYear()==year) {
			    		var day:Day=Day(centralContent.getChildByName('day'+item.eventDate.getDate()));
			    		trace("si");
			    		//trace(item.eventDate.getDate())
			    		//trace(centralContent.getChildByName('day'+item.eventDate.getDate()));
			    		if (item.enabled) {
			    			day.setEvent(item);
			    		} else {
			    			day.enabled=false;
			    		}	
			    }
			} 
		}
		
		private function onDayClick(event:MouseEvent):void {
			var day:Day=Day(event.target);
			var evt:SelectDayEvent;
			if (day.selected) {
				evt=new SelectDayEvent(SelectDayEvent.SELECT_DAY);
				selectedDate=day.dayData;
				selectedDates.addItem(day.dayData);
			} else {
				evt=new SelectDayEvent(SelectDayEvent.DESELECT_DAY);
				var index:int=selectedDates.getItemIndex(day.dayData);
				if (index!=-1) {
					selectedDates.removeItemAt(index);
					if (selectedDates.length==0) {
						selectedDate=null;
					}
				}
			}
			evt.data=day.dayData;
			dispatchEvent(evt);
		}
           
	}
}









